package com.contory.ssn_lgnd.app.maingame;

import java.util.ArrayList;

import android.util.FloatMath;
import android.util.Log;

import com.contory.ssn_lgnd.app.Assets;
import com.contory.ssn_lgnd.app.comp.ButtonObject;
import com.contory.ssn_lgnd.app.comp.ButtonObjectPtr;
import com.contory.ssn_lgnd.app.comp.DrawPtr;
import com.contory.ssn_lgnd.app.comp.TouchPtr;
import com.contory.ssn_lgnd.app.comp.UpdatePtr;
import com.contory.ssn_lgnd.app.comp.ViewObject;
import com.contory.ssn_lgnd.framework.Input.TouchEvent;
import com.contory.ssn_lgnd.framework.Pool.PoolObjectFactory;
import com.contory.ssn_lgnd.framework.Pool;
import com.contory.ssn_lgnd.framework.gl.Camera2D;
import com.contory.ssn_lgnd.framework.gl.SpriteBatcher;
import com.contory.ssn_lgnd.framework.math.OverlapTester;
import com.contory.ssn_lgnd.framework.math.Rectangle;
import com.contory.ssn_lgnd.framework.math.Vector2;

public class Controler implements DrawPtr, UpdatePtr, TouchPtr{
	static final int NULL_TOUCH_POINTER = -1;
	public static final int RIGHT = 0;
	public static final int LEFT = 1;
	public static final int NONE = -1;
	
	ControlerObject controlObj;
	SwapObject[] swapObjArr;
	ButtonObject opBtr;
	boolean pauseBool = false;
	
	public Controler(float frustumW, float frustumH){
		controlObj = new ControlerObject(frustumW, frustumH);
		swapObjArr = new SwapObject[1];
		//swapObjArr[LEFT] = new SwapObject(1.5f, 1.5f, SwapObject.DIR_LEFT);
		swapObjArr[RIGHT] = new SwapObject(18.5f, 1.5f, SwapObject.DIR_RIGHT);
		//swapObjArr[LEFT].onOtherSwapObject(swapObjArr[RIGHT]);
		//swapObjArr[RIGHT].onOtherSwapObject(swapObjArr[LEFT]);

	    opBtr = new ButtonObject();
	    opBtr.setXY_WH_TR(19f, 9f, 1.0F, 1.0F, Assets.TEX_REG_OPTION_BTR);
	    //opBtr.setRGBA(1, 1, 1, 0.5f);
	    //opBtr.setIcon(Assets.TEX_REG_OPTION_BTR);
	    opBtr.setTodo(new ButtonObjectPtr() {
			@Override
			public void todo() {
				if(pauseBool)
					pauseBool = false;
				else
					pauseBool = true;
				opBtr.excuteBool = false;
			}
		});
	}
	
	@Override
	public void draw(SpriteBatcher batcher) {
		swapObjArr[RIGHT].draw(batcher);
		//for (SwapObject swapObjArrChd : swapObjArr) 
			//swapObjArrChd.draw(batcher);
		controlObj.draw(batcher);
	}
	
	public void drawOpBtr(SpriteBatcher batcher){
		opBtr.draw(batcher);
	}
	
	@Override
	public void update(float deltaTime) {
		opBtr.update(deltaTime);
		if(pauseBool)
			return;
		controlObj.update(deltaTime);
		swapObjArr[RIGHT].update(deltaTime);
		//for (SwapObject swapObjArrChd : swapObjArr){ 
			//swapObjArrChd.update(deltaTime);
		//}
	}

	@Override
	public void setTouchEvent(TouchEvent touchEvent, float touchX, float touchY) {
		opBtr.setTouchEvent(touchEvent, touchX, touchY);
		if(pauseBool)
			return;
		controlObj.setTouchEvent(touchEvent, touchX, touchY);
		swapObjArr[RIGHT].setTouchEvent(touchEvent, touchX, touchY);
		//for (SwapObject swapObjArrChd : swapObjArr) 
			//swapObjArrChd.setTouchEvent(touchEvent, touchX, touchY);
	}
	
	public Vector2 getPointerNdir(){
		return controlObj.nDir;
	}
	
	public int getSwapBool(){
		//if(swapObjArr[LEFT].getSwapBool())
			//return Controler.LEFT;
		//else if(swapObjArr[RIGHT].getSwapBool())
		if(swapObjArr[RIGHT].getSwapBool())
			return Controler.RIGHT;
		else
			return Controler.NONE;
	}
	
	public class ControlerObject implements DrawPtr, UpdatePtr, TouchPtr{
		//final Camera2D cam;
		ViewObject dirPointerView;
		Rectangle bound;
		Vector2 centerPos;
		ArrowObject dirViewObj;
		Vector2 nDir;
		boolean controledBool = false;
		int touchPointer = NULL_TOUCH_POINTER;
		static final float POINTER_VIEW_BOUND_SCALRA = 1f;
		
		public ControlerObject(float boundW, float boundH){
			//this.cam = cam;
			dirPointerView = new ViewObject();
			dirPointerView.setXY_WH_TR(0, 0, 2, 2, Assets.tex_reg_controlerCircle);
			centerPos = new Vector2();
			dirViewObj = new ArrowObject();
			bound = new Rectangle(0, 0,
					boundW, boundH);
			nDir = new Vector2();
		}
		
		@Override
		public void setTouchEvent(TouchEvent touchEvent, float touchX,
				float touchY) {
			switch(touchEvent.type)
			{
				case TouchEvent.TOUCH_DOWN:
					if(!(OverlapTester.pointInRectangle(bound, touchX, touchY)  
							&& !OverlapTester.pointInRectangle(swapObjArr[0].bound, touchX, touchY)
							//&& !OverlapTester.pointInRectangle(swapObjArr[1].bound, touchX, touchY) 
							&& !OverlapTester.pointInRectangle(opBtr.getBound(), touchX, touchY)))
						return;	
					touchPointer = touchEvent.pointer;
					controledBool = true;
					centerPos.set(touchX, touchY);
					dirPointerView.x = touchX;
					dirPointerView.y = touchY;
					dirViewObj.setCenter(centerPos.x, centerPos.y);
				break;
				
				case TouchEvent.TOUCH_DRAGGED:
					if(touchPointer != touchEvent.pointer)
						return;
					if(!controledBool)
						break;
					dirPointerView.x = touchX;
					dirPointerView.y = touchY;
					nDir.x = dirPointerView.x - centerPos.x;
					nDir.y = dirPointerView.y - centerPos.y;
					float len = nDir.len();
					nDir = nDir.nor();
					dirViewObj.setOperated(nDir);
					if(len > POINTER_VIEW_BOUND_SCALRA){
						dirPointerView.x = centerPos.x + nDir.x * POINTER_VIEW_BOUND_SCALRA;
						dirPointerView.y = centerPos.y + nDir.y * POINTER_VIEW_BOUND_SCALRA;
					}
				break;
				
				case TouchEvent.TOUCH_UP:
					if(touchPointer != touchEvent.pointer)
						return;
					controledBool = false;
					touchPointer = NULL_TOUCH_POINTER;
					nDir.set(0, 0);
				break;
				
				default:
					controledBool = false;
					touchPointer = NULL_TOUCH_POINTER;
					nDir.set(0, 0);
				break;
			}
		}

		@Override
		public void update(float deltaTime) {
			//bound.lowerLeft.set(cam.getPosition().x - cam.getFrustumWidth() / 2, 
					//cam.getPosition().y - cam.getFrustumHeight() / 2);
			
			if(controledBool)
				dirViewObj.update(deltaTime);
		}

		@Override
		public void draw(SpriteBatcher batcher) {
			if(!controledBool)
				return;
			dirViewObj.draw(batcher);
			batcher.drawSprite(dirPointerView.x, dirPointerView.y, dirPointerView.w, dirPointerView.h, dirPointerView.tr);
		}
		
	}
	
	public class SwapObject implements DrawPtr, UpdatePtr, TouchPtr{
		//final Camera2D cam;
		ViewObject view;
		float rot = 0;
		Vector2 relativePosit;
		Rectangle bound;
		public static final int DIR_LEFT = 1;
		public static final int DIR_RIGHT = -1;
		
		private final static float ROT_VELOCITY_SCALA = 10.0f; 
		int touchPointer = NULL_TOUCH_POINTER;
		private final static float VIEW_WIDTH = 2.0f;
		private final static float VIEW_HEIGHT = 2.0f;
		
		private final static byte STATE_IDLE = 0;
		private final static byte STATE_CLICK = 1;
		private final static byte STATE_EXEC = 2;
		byte state = 0;
		boolean swapBool = false;
		SwapObject anotherObj = null;
		int rotDir = 1;
		
		float viewW;
		public SwapObject(float x, float y, int rotDir){
			view = new ViewObject();
			if(rotDir == DIR_LEFT)
				viewW = -VIEW_WIDTH;
			else
				viewW = VIEW_WIDTH;
			view.setXY_WH_TR(x, y, VIEW_WIDTH, VIEW_HEIGHT, Assets.tex_reg_swap);
			bound = new Rectangle(view.x - view.w / 2, view.y - view.y / 2, view.w, view.h);
			this.rotDir = rotDir;
		}
		
		@Override
		public void update(float deltaTime) {
			switch(state){
				case STATE_IDLE :
				break;
				
				case STATE_CLICK :
					swapBool = true;
					state = STATE_EXEC;
				break;
				
				case STATE_EXEC :
					swapBool = false;
					rot += deltaTime * ROT_VELOCITY_SCALA * rotDir;
					if(rotDir > 0){
						if(rot > Math.PI * 2){
							rot = 0;
							state = STATE_IDLE;
						}
					}
					else{
						if(rot < -Math.PI * 2){
							rot = 0;
							state = STATE_IDLE;
						}
					}
				break;
			}
		}
		
		public boolean getSwapBool(){
			return swapBool;
		}

		@Override
		public void draw(SpriteBatcher batcher) {
			batcher.drawSprite(view.x, view.y, viewW, view.h, rot, view.tr);
		}
		
		//public void onOtherSwapObject(SwapObject anotherObj){
			//this.anotherObj = anotherObj;
		//}
		
		@Override
		public void setTouchEvent(TouchEvent touchEvent, float touchX,
				float touchY) {
			if(!OverlapTester.pointInRectangle(bound, touchX, touchY))
				return;
			if(getSwapingBool())
				return;
			//if(anotherObj.getSwapingBool())
				//return;
			switch(touchEvent.type)
			{
				case TouchEvent.TOUCH_DOWN:
					touchPointer = touchEvent.pointer;
					if(state == STATE_IDLE)
						state = STATE_CLICK;
				break;
				
				case TouchEvent.TOUCH_DRAGGED:
				break;
				
				case TouchEvent.TOUCH_UP:
					touchPointer = NULL_TOUCH_POINTER;
				break;
				
				default:
				break;
			}
		}
		
		public boolean getSwapingBool(){
			if(state != STATE_IDLE)
				return true;
			else
				return false;
		}
	}
	
	
	public class ArrowObject implements DrawPtr, UpdatePtr{
		final int ARROW_NUM = 8;
		Vector2 center;
		ViewObject[] arrows;
		Vector2[] arrows_posits;
		boolean[] arrows_operated;
		float[] arrows_viewAngles;
		final float R = 2.0f;
		
		public ArrowObject(){
			center = new Vector2();
			arrows = new ViewObject[ARROW_NUM];
			arrows_posits = new Vector2[ARROW_NUM];
			arrows_viewAngles = new float[ARROW_NUM];
			arrows_operated = new boolean[ARROW_NUM];
			float angle = 0;
			for(int i = 0; i < ARROW_NUM; i++){
				arrows[i] = new ViewObject();
				arrows[i].setXY_WH_TR(0, 0, 1.0f, 1.0f, Assets.tex_reg_controlerArrow);
				arrows_posits[i] = new Vector2();
				arrows_posits[i].x = FloatMath.cos(angle);
				arrows_posits[i].y = FloatMath.sin(angle);
				arrows_viewAngles[i] = angle - (float)Math.PI / 2;
				arrows_operated[i] = false;
				angle += Math.PI / 4;
			}
		}
		
		public void setOperated(Vector2 dir){
			for(int i = 0; i < ARROW_NUM; i++){
				arrows_operated[i] = false;
				float scala = dir.dotProduct(arrows_posits[i]); 
				if(scala <= 1 && scala >= 0.9)
					arrows_operated[i] = true;
			}
		}
		
		public void setCenter(float x, float y){
			center.set(x, y);
		}
		
		@Override
		public void update(float deltaTime) {
			for (int i = 0; i < ARROW_NUM; i++) {
				arrows[i].x = center.x + arrows_posits[i].x * R;
				arrows[i].y = center.y + arrows_posits[i].y * R;
			}
		}

		@Override
		public void draw(SpriteBatcher batcher) {
			for (int i = 0; i < ARROW_NUM; i++) {
				if(arrows_operated[i] == true)
					batcher.drawSprite(arrows[i].x, arrows[i].y, arrows[i].w, arrows[i].h, arrows_viewAngles[i], 0.5f, 0.5f, 0.5f, 0.5f, arrows[i].tr);
				else
					batcher.drawSprite(arrows[i].x, arrows[i].y, arrows[i].w, arrows[i].h, arrows_viewAngles[i], 1.0f, 1.0f, 1.0f, 1.0f, arrows[i].tr);
			}
		}
	}
}
